﻿#region

using System;
using Jiubang.Communication.Common;
using Jiubang.Util;
using log4net;

#endregion

namespace Jiubang.Communication.Server{
    public abstract class Dispatcher{
        private readonly IRequestHandler[] handlers = new IRequestHandler[byte.MaxValue];
        private readonly ILog logger;
        private readonly RequestProtocol protocol = RequestProtocol.Instance;

        protected Dispatcher(){
            logger = LogManager.GetLogger(GetType());
        }

        /// <summary>
        /// 通讯框架服务端。程序通过该接口向客户端发送数据。
        /// </summary>
        protected internal IServer Server { get; internal set; }

        /// <summary>
        /// 通知框架服务端接收到客户端消息时将调用该方法。<br/>
        /// 方法体内部替换Buffer之必须使用BufferManager的FreeBuffer方法进行缓冲区回收，否则将造成缓冲区变小直至不可用<br/>
        /// </summary>
        /// <param name="args"></param>
        public virtual bool Accept(MessageContext args){
            byte handlerId = protocol.GetHandlerId(args);
            IRequestHandler handler = handlers[handlerId];
            if (handler == null){
                logger.Warn("RequestHandler[" + handlerId + "]未注册。消息内容为:" +
                            StringHelper.ConcatEnumerable(args.Segment.array, ","));
                return false;
            }
            return handler.Accept(args, Server);
        }

        /// <summary>
        /// 注册一个IRequestHandler用于处理消息
        /// </summary>
        /// <param name="unRegisteredHandler">待注册的实例</param>
        /// <exception cref="Exception">具有相同HandlerID的实例重复注册</exception>
        public void RegisterHandler(IRequestHandler unRegisteredHandler){
            byte registerId = unRegisteredHandler.HandlerId;

            IRequestHandler handler = handlers[registerId];
            if (handler != null)
                throw new Exception("ID=[" + registerId + "]被" + unRegisteredHandler.GetType().FullName + "重复注册");
            handlers[registerId] = unRegisteredHandler;
        }
    }
}